﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Data;

namespace ProgNetExtensions
{
    public static class StringExt
    {
        public static bool IsEmpty(this string str)
        {
            return str == null || str.Trim() == string.Empty || str == "";
        }
        public static bool IsNotEmpty(this string str)
        {
            return !IsEmpty(str);
        }

        public static string AppendString(this string str, string stringToAppend, bool onlyIfNotEmpty)
        {
            if (onlyIfNotEmpty && string.IsNullOrEmpty(str))
                return str;
            return str + stringToAppend;
        }
        public static string AppendString(this string str, string stringToAppend)
        {
            return AppendString(str, stringToAppend, true);
        }

        public static string AppendSpaceComa(this string str, bool onlyIfnotEmpty)
        {
            return AppendString(str, " ,", onlyIfnotEmpty);
        }
        public static string AppendSpaceComa(this string str)
        {
            return AppendSpaceComa(str, true);
        }

        public static string AppendComa(this string str, bool onlyIfnotEmpty)
        {
            return AppendString(str, ",", onlyIfnotEmpty);
        }
        public static string AppendComa(this string str)
        {
            return AppendComa(str, true);
        }

        public static string AppendSpace(this string str, bool onlyIfnotEmpty)
        {
            return AppendString(str, " ", onlyIfnotEmpty);
        }
        public static string AppendSpace(this string str)
        {
            return AppendSpace(str, true);
        }

        public static string AppendAnd(this string str, bool onlyIfnotEmpty)
        {
            return AppendString(str, " AND ", onlyIfnotEmpty);
        }
        public static string AppendAnd(this string str)
        {
            return AppendAnd(str, true);
        }

        public static string AppendOr(this string str, bool onlyIfnotEmpty)
        {
            return AppendString(str, " OR ", onlyIfnotEmpty);
        }
        public static string AppendOr(this string str)
        {
            return AppendOr(str, true);
        }

        public static string PutBetweenStrings(this string str, string leftString, string rigthString, bool onlyIfNotEmpty)
        {
            if (onlyIfNotEmpty && string.IsNullOrEmpty(str))
                return str;
            return leftString + str + rigthString;
        }
        public static string PutBetweenStrings(this string str, string leftString, string rigthString)
        {
            return PutBetweenStrings(str, leftString, rigthString, true);
        }

        public static string PutBetweenParenthesis(this string str, bool onlyIfnotEmpty)
        {
            return PutBetweenStrings(str, "(", ")", onlyIfnotEmpty);
        }
        public static string PutBetweenParenthesis(this string str)
        {
            return PutBetweenParenthesis(str, true);
        }

        public static string PutBetweenSingleQuotes(this string str, bool onlyIfnotEmpty)
        {
            return PutBetweenStrings(str, "'", "'", onlyIfnotEmpty);
        }
        public static string PutBetweenSingleQuotes(this string str)
        {
            return PutBetweenSingleQuotes(str, true);
        }

        public static string PutBetweenDoubleQuotes(this string str, bool onlyIfnotEmpty)
        {
            return PutBetweenStrings(str, "\"", "\"", onlyIfnotEmpty);
        }
        public static string PutBetweenDoubleQuotes(this string str)
        {
            return PutBetweenDoubleQuotes(str, true);
        }

        public static string EscapeSql(this string str, bool appendQuotes)
        {
            str = str.Replace("'", "''");
            if (appendQuotes)
                str = PutBetweenStrings(str, "'", "'", false);
            return str;
        }
        public static string EscapeSql(this string str)
        {
            return EscapeSql(str, true);
        }
    }

    public static class ObjectExt
    {
        public static object GetField(this object obj, string fieldName)
        {
            if (obj != null)
            {
                try
                {
                    FieldInfo fi = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                    if (fi != null)
                    {
                        return fi.GetValue(obj);
                    }
                }
                catch { }
            }
            return null;
        }
        public static object GetProperty(this object obj, string name)
        {
            if (obj != null)
            {
                try
                {
                    PropertyInfo pi = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
                    if (pi != null)
                        return pi.GetValue(obj, null);
                }
                catch { }
            }
            return null;
        }
        public static void SetProperty(this object obj, string name, object value)
        {
            if (obj != null)
            {
                try
                {
                    PropertyInfo pi = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
                    if (pi != null)
                        pi.SetValue(obj, value, null);
                }
                catch { }
            }
        }
        public static bool HasProperty(this object obj, string name)
        {
            if (obj != null)
            {
                try
                {
                    PropertyInfo pi = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
                    if (pi != null)
                        return true;
                }
                catch { }
            }
            return false;
        }
        public static string GetObjectName(this object obj)
        {
            return GetProperty(obj, "Name").AsString();
        }
        
        public static string AsString(this object obj)
        {
            if (obj == null)
                return "";
            return obj.ToString();
        }

        /// <summary>
        /// Returns object converted to int or 0 if it couldn't be parsed
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int AsInt(this object obj)
        {
            int i = 0;
            int.TryParse(obj.AsString(), out i);
            return i;
        }
        /// <summary>
        /// Clones the object
        /// </summary>
        /// <param name="sourceObj"></param>
        /// <returns></returns>
        public static object CloneObj(this object sourceObj)
        {
            if (sourceObj == null)
                return null;

            object clone = Activator.CreateInstance(sourceObj.GetType());
            foreach (FieldInfo fi in sourceObj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                Type ICloneType = fi.FieldType.GetInterface("ICloneable", true);
                if (ICloneType != null)
                {
                    ICloneable IClone = (ICloneable)fi.GetValue(sourceObj);
                    fi.SetValue(clone, IClone.Clone());
                }
                else
                {
                    if (fi.FieldType.GetInterface("IEnumerable", true) != null)
                        fi.SetValue(clone, Activator.CreateInstance(fi.FieldType));
                    else
                        fi.SetValue(clone, fi.GetValue(sourceObj));
                }
                Type IEnumerableType = fi.FieldType.GetInterface("IEnumerable", true);
                if (IEnumerableType != null)
                {
                    IEnumerable IEnum = (IEnumerable)fi.GetValue(sourceObj);
                    Type IListType = fi.FieldType.GetInterface("IList", true);
                    Type IDicType = fi.FieldType.GetInterface("IDictionary", true);
                    if (IListType != null)
                    {
                        IList list = (IList)fi.GetValue(clone);
                        foreach (object obj in IEnum)
                        {
                            ICloneType = obj.GetType().
                            GetInterface("ICloneable", true);
                            if (ICloneType != null)
                            {
                                ICloneable cloneObj = (ICloneable)obj;
                                list.Add(cloneObj.Clone());
                            }
                        }
                    }
                    else if (IDicType != null)
                    {
                        IDictionary dic = (IDictionary)fi.GetValue(clone);
                        foreach (DictionaryEntry de in IEnum)
                        {
                            ICloneType = de.Value.GetType().GetInterface("ICloneable", true);
                            if (ICloneType != null)
                            {
                                ICloneable cloneObj = (ICloneable)de.Value;
                                dic.Add(de.Key, cloneObj.Clone());
                            }
                        }
                    }
                }
            }
            EventInfo[] events = sourceObj.GetType().GetEvents();
            foreach (EventInfo ev in events)
            {
                Type tDelegate = ev.EventHandlerType;
                MethodInfo addMethod = ev.GetAddMethod();
                MethodInfo[] mis = ev.GetOtherMethods(true);
                foreach (MethodInfo mi in mis)
                {
                    Delegate del = Delegate.CreateDelegate(tDelegate, clone, mi);
                    addMethod.Invoke(clone, new object[] { del });
                }
            }

            return clone;
        }
    }
    
    public static class DataExt
    {
        public static DataTable SelectToTable(this DataTable dt, string select, int startRecord, int maxRecords)
        {
            DataTable d = dt.Clone();
            DataRow[] rows = dt.Select(select);
            for (int i = startRecord; i < startRecord + maxRecords; i++)
            {
                if (rows.Length > i)
                    d.ImportRow(rows[i]);
                else
                    break;
            }
            return d;
        }
        public static DataTable SelectToTable(this DataTable dt, string select)
        {
            return SelectToTable(dt, select, 0, int.MaxValue);
        }
        public static DataRow SelectFirstRow(this DataTable dt, string select)
        {
            DataRow[] rows = dt.Select(select);
            if (rows.Length > 0)
                return rows[0];
            return null;
        }


    }
}
